/*
 * system_exception.cpp
 *
 *  Created on: 2008-12-31
 *      Author: fanliangliang
 */

#include "system_exception.h"

#if defined(PLATFORM_WIN32)
#include <windows.h>
#include <winsock2.h>
#include <lmerr.h>
#else
#include <cstring>
#include <cerrno>
#endif


BEGIN_NAMESPACE_TOXIC

namespace detail {

#if defined(PLATFORM_WIN32)

	unsigned long lastError() {
		return GetLastError();
	}

	unsigned long lastNetworkError() {
		return WSAGetLastError();
	}

	string errorString(unsigned long id) {

		HMODULE hModule = 0; // default to system source

		DWORD formatFlags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER;

		// If id is in the network range, load the message source.
		if (id >= NERR_BASE && id <= MAX_NERR) {
			hModule = LoadLibraryEx(TEXT("netmsg.dll"), 0, DONT_RESOLVE_DLL_REFERENCES);
			formatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
		}
		else {
			formatFlags |= FORMAT_MESSAGE_FROM_SYSTEM;
		}

		HLOCAL buffer = 0;
		DWORD systemLocale = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);

		// Get the error code's textual description
		DWORD length = FormatMessage(formatFlags, hModule, id, systemLocale, (PTSTR)&buffer, 0, 0);

		if (hModule != 0) {
			FreeLibrary(hModule);
		}

		if (length != 0 && buffer != 0) {
			string result(static_cast<const char*>(buffer));
			LocalFree(buffer);
			return result;
		}
		else {
			return string();
		}
	}

#else

	unsigned long lastError() {
		return errno;
	}

	unsigned long lastNetworkError() {
		return errno;
	}

	string errorString(unsigned long id) {
		return string(strerror(id));
	}

#endif

} // namespace detail

END_NAMESPACE_TOXIC
